from datetime import timedelta, datetime
import random as rd
import time
import cv2
import cvtool
import numpy as np
import os
import requests
import json
from PIL import Image, ImageDraw, ImageFont
import displaymanager as sm
import config


def wait_for_next_update() -> int:
    if os.path.exists(config.CACHE_PATH):
        with open(config.CACHE_PATH) as f:
            cache = json.load(f)
            last_modified = cache["Last-Update"]
            last_time = datetime.strptime(
                last_modified, "%a, %d %b %Y %H:%M:%S %Z") + timedelta(hours=8)
            next_time_pred = last_time + \
                timedelta(minutes=16 + 2 * rd.random())
            time_to_wait = (next_time_pred - datetime.now()).total_seconds()
            time_to_wait = max(0, time_to_wait)
    else:
        time_to_wait = 0
    if time_to_wait > 290:
        print("需要等待的时长大于5分钟，自动退出")
        exit(0)
    time.sleep(time_to_wait)
    return time_to_wait


# 检查官网卫星图片是否更新，如果已经更新则重新下载该图像
def download_latest_photo(save_path=config.SRC_PATH) -> int:
    if os.path.exists(config.CACHE_PATH):
        with open(config.CACHE_PATH) as f:
            cache = json.load(f)
            last_modified = cache["Last-Update"]
    else:
        last_modified = "Sat, 12 Aug 2023 02:53:02 GMT"

    r = requests.get(config.URL, headers={'If-Modified-Since': last_modified})
    with open(config.LOG_PATH, 'a') as f:
        f.write(f"{r.status_code}: {json.dumps(dict(r.headers))}\n")
    if r.status_code == 200:
        with open(save_path, 'wb') as f:
            f.write(r.content)
        with open(config.CACHE_PATH, 'w') as f:
            last_modified = r.headers['Last-Modified']
            json.dump({"Last-Update": last_modified}, f)
    elif r.status_code == 304:
        pass
    else:
        cache["Error-Code"] = r.status_code
        cache["Error-Reason"] = r.reason
        with open(config.CACHE_PATH, 'w') as f:
            json.dump(cache, f)
    return r.status_code, last_modified


def get_earth_logo(src_img) -> np.ndarray:
    mask = cv2.imread(config.SRC_MASK_PATH)[:, :, 0:1]
    png = np.concatenate([src_img, mask], axis=2)
    png = png[88:10905, 68:10924]
    return png


# 在图像的右上角绘制北京时间
def draw_time(image: np.ndarray, time_string, pos='r') -> np.ndarray:
    # 解析时间字符串，转换成本地时间
    time_struct = datetime.strptime(
        time_string, "%a, %d %b %Y %H:%M:%S %Z") + timedelta(hours=8)

    # 格式化本地时间，例如 "2023年8月12日 星期六 11:07:59"
    local_time_string = time_struct.strftime("%H:%M %b %d\n%A\n%Y")

    # 创建一个ImageDraw对象，用于在图像上绘制
    image = Image.fromarray(image)
    draw = ImageDraw.Draw(image)

    # 选择一个有科技感的字体，例如 Eurostile Bold Extended
    # 你可以从这个网站下载这个字体 [1]
    font = ImageFont.truetype(config.TIME_FONT_PATH,
                              round(36*image.size[0]/1920))

    # 计算绘制文本的位置，右上角，留一些边距
    a, b, c, d = draw.textbbox((0, 0), local_time_string, font,)
    text_width = c - a
    image_width, image_height = image.size
    margin = 32
    x = image_width - text_width - margin if pos == 'r' else margin
    y = margin

    # 绘制文本，白色
    draw.text((x, y), local_time_string,
              fill="#eeeeee", font=font, align='right')

    # 返回修改后的图像
    return np.array(image)


def create_wallpaper(screen: sm.Screen, earth_logo: np.ndarray, align: tuple[float, float], logo_area: tuple[tuple[float, float], float], background_color=(0, 0, 0)) -> np.ndarray:
    earth_h, earth_w = earth_logo.shape[:2]
    area_center, area_scale = logo_area
    base_scale = min(screen.work.width/earth_w, screen.work.height/earth_h)
    real_scale = base_scale * area_scale

    scaled_logo = cvtool.resizeByScale(earth_logo, real_scale)
    scaled_logo = cvtool.EdgeGaussianBlur(scaled_logo, 5, 1)

    result = np.empty((screen.height, screen.width, 3), dtype=np.uint8)
    result[:, :] = np.array(background_color)
    result = cvtool.pinnedPaste(result, scaled_logo, align, area_center)
    return result


def getAreas(name: str) -> tuple[tuple[float, float], float]:
    areas = {
        'world': ((0.5, 0.5), 0.9),
        'china': ((0.3, 0.27), 2.5),
    }
    if name in areas:
        return areas[name]
    else:
        print(f"location '{name}' not exists")
        return areas['world']


if __name__ == "__main__":
    DEBUG = False
    # DEBUG = True
    if not DEBUG:
        wait_for_next_update()
        code, last_modified = download_latest_photo(config.SRC_PATH)
    else:
        code = 200
        last_modified = (datetime.now() - timedelta(hours=8)
                         ).strftime("%a, %d %b %Y %H:%M:%S UTC")

    if code == 200:
        src_img = cv2.imread(config.SRC_PATH)
        earth_logo = get_earth_logo(src_img)
        displayManager = sm.DisplayManager()
        if 'Screen-1' in displayManager:
            screen = displayManager['Screen-1']
            align = screen.end_center
            background_color = (20, 10, 5)
            area = getAreas('world')
            wallpaper = create_wallpaper(screen, earth_logo, align, area)
            wallpaper = draw_time(wallpaper, last_modified)
            screen.setWallpaper(wallpaper)
        if 'Screen-2' in displayManager:
            screen = displayManager['Screen-2']
            align = screen.center
            background_color = (20, 10, 5)
            area = getAreas('china')
            wallpaper = create_wallpaper(screen, earth_logo, align, area)
            screen.setWallpaper(wallpaper)
        displayManager.default_wallpaper_painter = lambda screen: create_wallpaper(
            screen, earth_logo, screen.end_center, getAreas('world'), background_color=(20, 10, 5))
        displayManager.full_update()
